package cc.shacocloud.mirage.core;

import cc.shacocloud.mirage.bean.*;
import cc.shacocloud.mirage.bean.aware.Aware;
import cc.shacocloud.mirage.env.EnvironmentAware;
import cc.shacocloud.mirage.utils.ClassUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用的应用对象工厂，基于 {@link AnnotationBeanFactory} 拓展支持应用整合
 *
 * @author 思追(shaco)
 */
public class GenericApplicationBeanFactory extends AnnotationBeanFactory {
    
    /**
     * 应用上下文
     */
    private final ConfigurableApplicationContext applicationContext;
    
    
    public GenericApplicationBeanFactory(@NotNull ClassScanner classScanner,
                                         @NotNull ConfigurableApplicationContext applicationContext) {
        super(classScanner);
        this.applicationContext = applicationContext;
    }
    
    public GenericApplicationBeanFactory(@NotNull ClassScanner classScanner,
                                         @NotNull ConditionHandler conditionHandler,
                                         @NotNull ConfigurableApplicationContext applicationContext) {
        super(classScanner, conditionHandler);
        this.applicationContext = applicationContext;
    }
    
    public GenericApplicationBeanFactory(@NotNull ClassScanner classScanner,
                                         @NotNull QualifierHandler qualifierHandler,
                                         @NotNull ScopeHandler scopeHandler,
                                         @NotNull ConditionHandler conditionHandler,
                                         @NotNull ConfigurableApplicationContext applicationContext) {
        super(classScanner, qualifierHandler, scopeHandler, conditionHandler);
        this.applicationContext = applicationContext;
    }
    
    @Override
    public void init() {
        super.init();
        
        // 初始化应用事件对象实例
        List<ApplicationListener<?>> applicationListeners = getCandidateApplicationEventBeans();
        applicationContext.getEventMulticaster().addApplicationListeners(applicationListeners);
    }
    
    /**
     * 拓展基本的 {@link BeanFactory} 提供的 {@link Aware}，提供应用级别的 {@link ApplicationContextAware}
     *
     * @param beanName 对象名称
     * @param bean     对象实例
     */
    @Override
    protected void invokeAwareMethods(@Nullable String beanName, @NotNull Object bean) {
        super.invokeAwareMethods(beanName, bean);
        
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(applicationContext);
        }
        
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(applicationContext.getEnvironment());
        }
    }
    
    /**
     * 获取满足应用事件监听器的对象
     */
    protected List<ApplicationListener<?>> getCandidateApplicationEventBeans() {
        return getBeanClassForType(Object.class)
                .entrySet()
                .stream()
                .filter(entry -> {
                    Class<?> beanClass = entry.getValue();
                    return ClassUtil.isAssignable(ApplicationListener.class, beanClass);
                })
                .map(entry -> (ApplicationListener<?>) getBean(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }
    
}
